// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/CharacterMovementComponent.h"
#include "NativeGameplayTags.h"

#include "LyraCharacterMovementComponent.generated.h"

#define UE_API LYRAGAME_API

class UObject;
struct FFrame;

LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_MovementStopped); // 声明游戏标签：移动停止

/**
 * FLyraCharacterGroundInfo
 *
 *	角色下方地面的信息。仅在需要时更新。
 */
USTRUCT(BlueprintType)
struct FLyraCharacterGroundInfo
{
	GENERATED_BODY()

	FLyraCharacterGroundInfo()
		: LastUpdateFrame(0) // 最后更新帧
		, GroundDistance(0.0f) // 地面距离
	{}

	uint64 LastUpdateFrame; // 最后更新帧

	UPROPERTY(BlueprintReadOnly)
	FHitResult GroundHitResult; // 地面碰撞结果

	UPROPERTY(BlueprintReadOnly)
	float GroundDistance; // 地面距离
};

/**
 * ULyraCharacterMovementComponent
 *
 *	本项目使用的基础角色移动组件类。
 */
UCLASS(MinimalAPI, Config = Game)
class ULyraCharacterMovementComponent : public UCharacterMovementComponent
{
	GENERATED_BODY()

public:

	UE_API ULyraCharacterMovementComponent(const FObjectInitializer& ObjectInitializer);

	/**
	 * 模拟移动
	 */
	UE_API virtual void SimulateMovement(float DeltaTime) override;

	/**
	 * 检查是否可以尝试跳跃
	 */
	UE_API virtual bool CanAttemptJump() const override;

	/**
	 * 返回当前地面信息。调用此函数将在信息过时时更新地面信息。
	 */
	UFUNCTION(BlueprintCallable, Category = "Lyra|CharacterMovement")
	UE_API const FLyraCharacterGroundInfo& GetGroundInfo();

	/**
	 * 设置复制加速度
	 */
	UE_API void SetReplicatedAcceleration(const FVector& InAcceleration);

	//~UMovementComponent 接口
	/**
	 * 获取增量旋转
	 */
	UE_API virtual FRotator GetDeltaRotation(float DeltaTime) const override;
	/**
	 * 获取最大速度
	 */
	UE_API virtual float GetMaxSpeed() const override;
	//~UMovementComponent 接口结束

protected:

	/**
	 * 初始化组件
	 */
	UE_API virtual void InitializeComponent() override;

protected:

	// 角色的缓存地面信息。不要直接访问！仅在通过GetGroundInfo()访问时更新。
	FLyraCharacterGroundInfo CachedGroundInfo; // 缓存地面信息

	UPROPERTY(Transient)
	bool bHasReplicatedAcceleration = false; // 是否有复制加速度
};

#undef UE_API